﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace PlaystationNetworkAPI.Core.Common
{

    /// <summary>
    /// Class that will handle the generic parsing features.
    /// </summary>
    class Parser
    {
        internal string _HtmlCode;
        internal string _InnerTextRegexPattern;
        internal string _ImageSourceRegexPattern;
        internal string _AHrefRegexPattern;

        /// <summary>
        /// Parser constructor.
        /// </summary>
        /// <param name="htmlCode">Html code that will be parsed.</param>
        internal Parser(string htmlCode)
        {
            _HtmlCode = htmlCode;
            _InnerTextRegexPattern = Properties.Settings.Default.Common_Parser_InnerTextRegexPattern;
            _ImageSourceRegexPattern = Properties.Settings.Default.Common_Parser_ImageSourceRegexPattern;
            _AHrefRegexPattern = Properties.Settings.Default.Common_Parser_AHrefRegexPattern;
        }


        /// <summary>
        /// Get the inner text from a html tag.
        /// </summary>
        /// <param name="tagName">Name of the Html tag.</param>
        /// <param name="attributeName">Name of the Html tag attribute.</param>
        /// <param name="attributeValue">Value of the Html tag attribute.</param>
        /// <returns>maching result.</returns>
        internal string GetInnerText(string tagName, string attributeName, string attributeValue, string toRemove, string htmlCode)
        {
            string regexPattern = string.Format(_InnerTextRegexPattern, tagName, attributeName, attributeValue);

            if (Regex.IsMatch(htmlCode, regexPattern, RegexOptions.IgnoreCase))
            {
                string returnedValue = Regex.Match(htmlCode, regexPattern, RegexOptions.IgnoreCase).Value;

                string strippedValue = StripHtmlTags(returnedValue).Trim();

                if (!string.IsNullOrEmpty(toRemove))
                {
                    strippedValue = strippedValue.Replace(toRemove, string.Empty).Trim();
                }

                return CorrectString(strippedValue);
            }
            else
            {
#if DEBUG
                throw new ApplicationException("The regular expression pattern \"" + regexPattern + "\" has no match.");
#else
                return null;
#endif
            }
        }

        /// <summary>
        /// Get the source path for the image knowing only part of the path.
        /// </summary>
        /// <param name="knowPathPart">Part of the path.</param>
        /// <returns>full path of the image.</returns>
        internal string GetImgSource(string knowPathPart, string htmlCode)
        {
            string regexPattern = string.Format(_ImageSourceRegexPattern, knowPathPart);

            if (Regex.IsMatch(htmlCode, regexPattern, RegexOptions.IgnoreCase))
            {
                return CleanUpUrl(Regex.Match(htmlCode, regexPattern, RegexOptions.IgnoreCase).Groups["imageSource"].Value);
            }
            else
            {
#if DEBUG
                throw new ApplicationException("The regular expression pattern \"" + regexPattern + "\" has no match.");
#else
                return null;
#endif
            }
        }

        internal string GetAHref(string knowPathPart, string htmlCode)
        {
            string regexPattern = string.Format(_AHrefRegexPattern, knowPathPart);

            if (Regex.IsMatch(htmlCode, regexPattern, RegexOptions.IgnoreCase))
            {
                return Regex.Match(htmlCode, regexPattern, RegexOptions.IgnoreCase).Groups["hrefLocation"].Value;
            }
            else
            {
#if DEBUG
                throw new ApplicationException("The regular expression pattern \"" + regexPattern + "\" has no match.");
#else
                return null;
#endif
            }
        }

        internal string StripHtmlTags(string source)
        {
            char[] array = new char[source.Length];
            int arrayIndex = 0;
            bool inside = false;

            for (int i = 0; i < source.Length; i++)
            {
                char let = source[i];
                if (let == '<')
                {
                    inside = true;
                    continue;
                }
                if (let == '>')
                {
                    inside = false;
                    continue;
                }
                if (!inside)
                {
                    array[arrayIndex] = let;
                    arrayIndex++;
                }
            }
            return new string(array, 0, arrayIndex);
        }

        internal string CleanUpUrl(string source)
        {
            source = source.Substring(source.IndexOf("http"), source.Length);
            if (source.Contains("\""))
            {
                source = source.Remove(source.IndexOf("\""));
            }

            return source;
        }

        internal string CorrectString(string source)
        {
            source = source.Replace("&#039;", "'");

            return source;
        }

        internal int? TryParseNullableInt(string source)
        {
            try
            {
                return Convert.ToInt32(source);
            }
            catch
            {
#if DEBUG
                throw new ApplicationException("The value \"" + source + "\" could not be converted the integer.");
#else
                return null;
#endif
            }
        }
    }
}
